package zinx

import (
	"awesomeProject/zinx/utils"
	"awesomeProject/zinx/ziface"
	"errors"
	"fmt"
	"net"
)

type Server struct {
	Name      string
	IpVersion string
	Ip        string
	Port      int
	MsgHandle ziface.IHandler
	ConnMr    ziface.IConnManager
}

func CallBackToClient(conn *net.TCPConn, data []byte, cnt int) error {
	fmt.Println("[Conn Handle]CallBackToClient...")
	if _, err := conn.Write(data[:cnt]); err != nil {
		fmt.Println("write back buf err", err)
		return errors.New("CallBackToClient error")
	}
	return nil
}

func (s *Server) Start() {
	fmt.Printf("[Start] Server Listenner at IP :%s,Port:%d,is starting\n", s.Ip, s.Port)
	go func() {
		//开启工作池
		s.MsgHandle.StartWorkerPool()

		addr, err := net.ResolveTCPAddr(s.IpVersion, fmt.Sprintf("%s:%d", s.Ip, s.Port))
		if err != nil {
			fmt.Println("resolve tcp addt error:", err)
			return
		}
		listenner, err := net.ListenTCP(s.IpVersion, addr)
		if err != nil {
			fmt.Println("listen", s.IpVersion, ",err:", err)
			return
		}
		fmt.Println("start Zinx Server succ", s.Name, "succ Listenning...")
		var cid uint32
		cid = 0
		for {
			conn, err := listenner.AcceptTCP()
			if err != nil {
				fmt.Println("Accept err", err)
				continue
			}
			if s.ConnMr.Len() > utils.GlobalObject.MaxConn {
				conn.Close()
				continue
			}
			dealConn := NewConnection(s,conn, cid, s.MsgHandle)
			cid++
			go dealConn.Start()
		}
	}()
}

func (s *Server) Stop() {
	s.ConnMr.ClearConn()
}

func (s *Server) Server() {
	s.Start()
	select {}
}

func (s *Server) AddRouter(msgId uint32, router ziface.IRouter) {
	s.MsgHandle.AddRouter(msgId, router)
	fmt.Println("Add Router Succ!!")
}

func NewServer(name string) ziface.IServer {
	s := &Server{
		Name:      name,
		IpVersion: "tcp4",
		Ip:        utils.GlobalObject.Host,
		Port:      utils.GlobalObject.TcpPort,
		MsgHandle: NewMsgHandle(),
		ConnMr:    NewConnManager(),
	}
	return s
}
